package cn.demoncat.util.lang;

import cn.demoncat.util.exception.ParamRuntimeException;
import cn.demoncat.util.lang.constant.StringConstant;
import cn.demoncat.util.lang.entity.Result;
import cn.demoncat.util.lang.enums.DateFormatEnum;
import cn.demoncat.util.lang.enums.DateFormatNumEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.time.LocalDate;
import java.util.Date;

/**
 * 描述：日期工具
 *
 * Date相关操作建议使用用LocalDateUtil
 * 
 * @author yxl
 *
 * @since 2016-8-11
 */
public class DateUtil {

	// 12星座
	private static final String[] CONSTELLATION = { "摩羯座", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座" };
	// 星座的月分隔日
	private static final int[] CONSTELLATION_DAY = { 20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22 };
	// 12生肖
	private static final String[] ZODIAC = { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };

	/**
	 * 获取生肖
	 * 
	 * @param year	年份，不能小于0
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年8月31日
	 */
	public static String getZodiac(int year) {
		if (year < 0) {
			return StringConstant.EMPTY;
		}
		// 最小公元前20年：通常以1900鼠年起始计算，为了兼容古代所以往前推算到了-20鼠年
		return ZODIAC[(year + 20) % ZODIAC.length];
	}

	/**
	 * 获取生肖
	 * 
	 * @param date
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年8月31日
	 */
	public static String getZodiac(LocalDate date) {
		return getZodiac(date.getYear());
	}

	/**
	 * 获取星座
	 * 
	 * @param month
	 * @param day
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年8月31日
	 */
	public static String getConstellation(int month, int day) {
		// 分隔日前 = month，分隔日后 = month + 1
		return day < CONSTELLATION_DAY[month] ? CONSTELLATION[month] : CONSTELLATION[month + 1];
	}

	/**
	 * 获取星座
	 * 
	 * @param date
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年8月31日
	 */
	public static String getConstellation(LocalDate date) {
		return getConstellation(date.getMonthValue(), date.getDayOfMonth());
	}

	/**
	 * 获取周岁
	 * 
	 * @param birthday	生日
	 * @param target	计算日期
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月2日
	 */
	public static int getAge(LocalDate birthday, LocalDate target) {
		return LocalDateUtil.betweenYear(birthday, target);
	}

	/**
	 * 获取周岁
	 * 
	 * @param birthday	生日
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月2日
	 */
	public static int getAge(LocalDate birthday) {
		return getAge(birthday, LocalDate.now());
	}

	/**
	 * 
	 * 功能描述：指定时间的字符串
	 *
	 * @param format 日期格式 {@link DateFormatEnum } 
	 * 
	 * @return 时间字符串
	 * 
	 * @author yxl
	 *
	 * @since 2016-8-11
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static String getDateStr(Date date, DateFormatEnum format) {
		if (date == null)
			return null;
		if (format == null)
			throw ParamRuntimeException.NULL;
		return DateFormatUtils.format(date, format.getValue());
	}

	/**
	 * 
	 * 功能描述：指定时间的数值型字符串
	 *
	 * @param format 数值型日期格式 {@link DateFormatNumEnum } 
	 * 
	 * @return 时间字符串
	 * 
	 * @author yxl
	 *
	 * @since 2016-8-11
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static String getDateNum(Date date, DateFormatNumEnum format) {
		if (date == null)
			return null;
		if (format == null)
			throw ParamRuntimeException.NULL;
		return DateFormatUtils.format(date, format.getValue());
	}

	/**
	 * 
	 * 功能描述：将时间字符串转换为时间 
	 *
	 * @param date   日期字符串
	 * @param format 日期格式 {@link DateFormatEnum } 
	 * @return 参数为空或参数不符合约定：抛异常
	 * 
	 * @author yxl
	 *
	 * @since 2016-11-15
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static Date parseStrDate(String date, DateFormatEnum format) {
		if (StringUtils.isBlank(date)) {
			return null;
		}
		if (format == null)
			throw ParamRuntimeException.NULL;
		try {
			return DateUtils.parseDate(date, format.getValue());
		} catch (ParseException e1) {
			throw new ParamRuntimeException(Result.TIME_FORMAT_ERROR.getMsg(), e1);
		}
	}

	/**
	 * 
	 * 功能描述：将数值型时间字符串转换为时间
	 *
	 * @param date    数值型日期字符串
	 * @param format  数值型日期格式 {@link DateFormatNumEnum }
	 * @return 参数为空或不符合约定，抛异常
	 * 
	 * @author yxl
	 *
	 * @since 2016-11-15
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static Date parseNumDate(String date, DateFormatNumEnum format) {
		if (StringUtils.isBlank(date)) {
			return null;
		}
		if (format == null)
			throw ParamRuntimeException.NULL;
		try {
			return DateUtils.parseDate(date, format.getValue());
		} catch (ParseException e1) {
			throw new ParamRuntimeException(Result.TIME_FORMAT_ERROR.getMsg(), e1);
		}
	}

}
